/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.pokemon.dao;

import com.pokemon.entities.Badge;
import com.pokemon.entities.Stadium;
import com.pokemon.entities.Trainer;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

/**
 *
 * @author Martin Strasek
 */
@Component
@Repository("BadgeDAOJpa")
public class BadgeDAOJpa implements BadgeDAO{
    
    @PersistenceContext
    private EntityManager em;
    
    public void setEm(EntityManager em) {
        this.em = em;
    }
    
    /*
     * Just for backward compatibility
     */
    public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory){
        throw new UnsupportedOperationException("Not supported");
    }

    
    public void addBadge(Badge badge) {
        if ((badge == null) || (badge.getId() != null) || (badge.getTrainer() == null) || (badge.getStadium() == null)) {
            throw new NullPointerException("Badge, its trainer or stadium is null or its id is non-null");
        }
        this.validateBadge(badge);
        
        em.persist(badge);
    }
    
    /**
     * Method validates attributes trainer and stadium of badge.
     * It checks if such a trainer or stadium already exists in the database or if stadium has got a trainer.
     * It also checks if badge stadium does not belong to trainer which will be rewarded by this badge.
     * 
     * @param badge the badge to be validated
     * @throws IllegalArgumentException
     */
    
    public void validateBadge(Badge badge) throws IllegalArgumentException,NullPointerException {
        Trainer trainer = em.find(Trainer.class, badge.getTrainer().getId());
        Stadium stadium = em.find(Stadium.class, badge.getStadium().getId());

        if (!trainer.equals(badge.getTrainer()) || !stadium.equals(badge.getStadium())) {
            throw new IllegalArgumentException("Trainer or stadium do not exist in the database");
        } else if ((stadium.getTrainer() == null)) {
            throw new NullPointerException("Stadium does not have a trainer");
        } else if (trainer.equals(stadium.getTrainer())) {
            throw new IllegalArgumentException("Trainer can not be awarded a badge of his own stadion");
        }
    }
    
    
    public Badge getBadge(Long id) {
        if (id == null) {
            throw new IllegalArgumentException("Parameter id is null");
        }
        
        Badge badge = em.find(Badge.class, id);
        
        return badge;
    }

    
    public void updateBadge(Badge badge) {
        if ((badge == null) || (badge.getTrainer() == null) || (badge.getStadium() == null)) {
            throw new NullPointerException("Badge, its trainer, stadium or id is null");
        }
        if (badge.getId()==null)
            throw new IllegalArgumentException("ID is null");
        this.validateBadge(badge);
       
            
        Badge updatedBadge = em.merge(em.find(Badge.class, badge.getId()));
        updatedBadge.setStadium(badge.getStadium());
        updatedBadge.setTrainer(badge.getTrainer());
        
    }

    
    public void removeBadge(Badge badge) {
        if (badge == null || badge.getId() == null) {
            throw new IllegalArgumentException("Badge is null or badge id is null");
        }
      
        Badge badgeToRemove = em.find(Badge.class, badge.getId());
        em.remove(badgeToRemove);
        
    }

    
    public List<Badge> getAllBadges() {
        Query query = em.createQuery("SELECT b FROM Badge b");
        return (List<Badge>) query.getResultList();
    }
    
}